package com.bupt.config.interceptor;


import com.alibaba.fastjson.JSONObject;
import com.bupt.annotation.AccessLimit;
import com.bupt.config.interceptor.thread.CurrentUserInfo;
import com.bupt.config.sys.LoginUserStatusConfig;
import com.bupt.constants.ResponseResult.RetCodeConstant;
import com.bupt.dao.TbSystemUserMapper;
import com.bupt.dto.sys.UserDto;
import com.bupt.model.TbSystemUser;
import com.bupt.model.TbSystemUserExample;
import com.bupt.utils.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 检验用户登陆以及其他操作  增加接口是否可用的操作
 * Created by Administrator on 2018/4/29 0029.
 */
@Slf4j
@Component
public class AccessLimitInterceptor extends HandlerInterceptorAdapter {
    /*  redis的基本操作   */

    private RedisTemplate redisTemplate;

    public AccessLimitInterceptor() {
    }

    public AccessLimitInterceptor(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }


    @Resource
    private  TbSystemUserMapper tbSystemUserMapper;


    // 拦截器的处理
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler)
            throws Exception {
        //设置我们的请求可以跨域请求
        ISetHeader.preSetCommonHeader(request, response);
        if (handler instanceof HandlerMethod) {
            // 获取到请求方法的对象
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            AccessLimit methodAnnotation = handlerMethod.getMethodAnnotation(AccessLimit.class);
            // 检查方法上面是否存在这个注解
            if (null != methodAnnotation) {

                /*验证验证码是否正确  end*/
                // 登录验证
                if (methodAnnotation.isLogIn()) {
                    // 获取到登陆的token
                    String tokenKey = TokenUtils.getTokenFromHeaderOrRequestParamOrCookie(request);
                    if (null == tokenKey || tokenKey.trim().equals("")) {
                        ExploreWriteUtils.writeMessage(RetCodeConstant.NOT_LOGIN, request, response, "您没有登录，无法操作");
                        return false;
                    }
                    // 从redis 里面获取
                    UserDto userDto = RedisUtils.getObjectByOriKey(tokenKey, redisTemplate, UserDto.class);
                    /* redis里面没有 并不一定说明没有登陆 这个时候时候访问数据库查看最后一次登陆的token */
                    if (null == userDto) {
                        TbSystemUserExample tbSystemUserExample = new TbSystemUserExample();
                        tbSystemUserExample.createCriteria().andLastLoginTokenEqualTo(tokenKey);
                        List<TbSystemUser> tbSystemUsers = tbSystemUserMapper.selectByExample(tbSystemUserExample);
                        if (null != tbSystemUsers && tbSystemUsers.size() > 0) {
                            TbSystemUser tbSystemUser = tbSystemUsers.get(0);
                           userDto = JSONObject.parseObject(JSONObject.toJSONString(tbSystemUser), UserDto.class);
                        }
                        // 设置新的数据
                       RedisUtils.setObjectByOriKey(tokenKey, redisTemplate, userDto);
                    }
                   // CurrentUserInfo.putCurrentUser.accept(userDto);
                    CurrentUserInfo.putCurrentUser(userDto);
                }
                // 设置当前的登陆用户
            }
        }
        return true;
    }

    @Override
    public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler,
                           ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(
            @NonNull HttpServletRequest request, HttpServletResponse response, @NonNull Object handler, Exception ex)
            throws Exception {
        // 移除当前的登陆用户
        CurrentUserInfo.removeCurrentLoginUser();
        if (response.getStatus() == 500 || response.getStatus() == 404) {
            if (null != ex) {
                ExploreWriteUtils.writeMessage(RetCodeConstant.FAIL, request, response, "系统内部错误，请联系管理员 " +
                        "message=" + ex.getMessage());
            } else {
                ExploreWriteUtils.writeMessage(RetCodeConstant.FAIL, request, response, "系统内部错误，请联系管理员");
            }
            return;
        }
        super.afterCompletion(request, response, handler, ex);
    }



    //序列化的对象
    // 防止刷新的操作
    @Data
    private static class IntervalClass {
        private long preClickTime;// 上一次点击时间
        private long firstClickTime; // 第一次点击时间
        private int clickCount;// 点击次数
    }
}

